<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <script>
        //定义存储桶构成
        class hashBucketNode {
            constructor(data) {
                this.data = data
                this.next = null
            }
        }
        //定义哈希表节点构成 可使用链表存储，节约空间复杂度，但时间复杂度过高
        class hashSetNode {
            constructor(buckets, bucketsData) {
                this.buckets = buckets
                this.bucketsData = new hashBucketNode(bucketsData)
                this.next = null
            }
        }
        // 思路，采用MyHashSet单链表/数组嵌套Buckets链表，避免使用数组造成内存浪费
        var MyHashSet = function() {
            //创建并初始化hash表
            this.hashSet = new Array(997).fill(null)
        };

        /** 
         * @param {number} key
         * @return {void}
         */
        MyHashSet.prototype.add = function(key) {
            //判断该值是否存在，若存在则直接退出该函数
            if (this.contains(key)) {
                return
            }
            // 如果当前桶存在，则直接向桶内添加节点即可
            const Bucket = this.hashFunc(key)
            if (this.hashSet[Bucket]) {
                let current = new hashBucketNode(key)
                current.next = this.hashSet[Bucket]
                this.hashSet[Bucket] = current
            } else {
                this.hashSet[Bucket] = new hashBucketNode(key)
                d
            }
        };
        /** 
         * @param {number} key
         * @return {void}
         */
        MyHashSet.prototype.remove = function(key) {
            // 若该值不存在，则退出函数
            if (!this.contains(key)) {
                return
            } else {
                // 声明provide变量用于存放前置节点
                let provide = null
                for (let i = this.hashSet[this.hashFunc(key)]; i != null; provide = i, i = i.next) {
                    if (i.data === key) {
                        // 若当前节点的data匹配key，且为头结点，则将头结点移除，i.next赋值给该存储桶
                        if (!provide) {
                            this.hashSet[this.hashFunc(key)] = i.next
                            return
                        }
                        // 否则将前置节点provide的下一个节点next赋值为当前节点i的下一个节点next
                        provide.next = i.next
                        return
                    }
                }
            }
        };

        /** 
         * @param {number} key
         * @return {boolean}
         */
        MyHashSet.prototype.contains = function(key) {
            const Bucket = this.hashFunc(key)
                // 若该桶从未启用，则表示不存在该值
            if (!this.hashSet[Bucket]) {
                return false
            } else {
                for (let i = this.hashSet[Bucket]; i != null; i = i.next) {
                    if (i.data === key) {
                        return true
                    }
                }
            }
            return false
        };
        // 定义映射存储桶的哈希函数
        MyHashSet.prototype.hashFunc = function(key) {
            return key % 997
        };
        /**
         * Your MyHashSet object will be instantiated and called as such:
         * var obj = new MyHashSet()
         * obj.add(key)
         * obj.remove(key)
         * var param_3 = obj.contains(key)
         */
        var a = new MyHashSet()
        a.add(11)
        a.add(12)
        a.add(13)
        console.log(a.contains(13))
        a.remove(13)
        console.log(a.contains(13))
        console.log('a.hashSet :>> ', a.hashSet);
    </script>
</body>

</html>